
use std::ops::Add;
use std::rc::Rc;
use std::cell::RefCell;
use crate::lexer::Token;

#[derive(lombok::Getter)]
#[derive(Debug)]
struct Node
{
    parent_node: Option<Rc<RefCell<Node>>>,
    left_node: Option<Rc<RefCell<Node>>>,
    right_node: Option<Rc<RefCell<Node>>>,
    data: Option<Token>
}


impl Node
{
    pub fn new(
        parent_node: Option<Rc<RefCell<Node>>>,
        left_node: Option<Rc<RefCell<Node>>>,
        right_node: Option<Rc<RefCell<Node>>>,
        data: Option<Token>
        ) -> Rc<RefCell<Self>>
    {
        let node = Self {
            parent_node,
            left_node,
            right_node,
            data
        };
        Rc::new(RefCell::new(node))
    }

    pub fn set_left_node(&mut this, left: Rc<RefCell<Self>>)
    {
        left.borrow_mut().parent_node = Option::Some(self);
        self.left_node = Option::Some(left);

    }

    pub fn size_left(&self) -> usize
    {
        let mut count = 0;

        let mut next = self.left_node.clone();
        loop {
            if let Some(r) = next {
                count += 1;
                next = r.borrow().left_node.clone();
                continue;
            }
            break;
        }
        count
    }

    pub fn size_right(&self) -> usize
    {
        let mut count = 0;

        let mut next = self.right_node.clone();
        loop {
            if let Some(r) = next {
                count += 1;
                next = r.borrow().right_node.clone();
                continue;
            }
            break;
        }
        count
    }

    pub fn print_left(&self)
    {
        let size_left = self.size_left();
        for _ in 0..size_left {
            print!("\t");
        }

        if let Some(t) = &self.data {
            print!("{}", t.get_value());
        }
        if let Some(left) = &self.left_node {
            left.borrow().print_left();
            if let Some(right) = &self.right_node {
                right.borrow().print_value();
                println!();
            }
        }
        
    }


    pub fn print_value(&self)
    {
        if let Some(t) = &self.data {
            println!("{}", t.get_value());
        }
        if self.left_node.is_some() {
            println!("left_node:");
            self.left_node
                .as_ref()
                .unwrap()
                .borrow()
                .print_value();
        }
        if self.right_node.is_some() {
            println!("right_node:");
            self.right_node
                .as_ref()
                .unwrap()
                .borrow()
                .print_value();
        }
    }
}


/// 解析优先级
/// =
/// ()
pub(crate)struct Parser;
impl Parser {
    pub fn read_token_vec_to_()
    {
        let vec_left_node: Vec<Node> = vec![];
    }
}




mod tests {
    use crate::lexer::TokenType;
    use super::*;

    #[test]
    fn test_node_print()
    {
        let mut vec: Vec<Rc<RefCell<Node>>> = vec![];
        for index in 0..5
        {
            let left = Node::new(
                Option::None,
                Option::None,
                Option::None,
                Option::Some(Token::new(TokenType::None, format!("node {} left", index)))
            );
            let right = Node::new(
                Option::None,
                Option::None,
                Option::None,
                Option::Some(Token::new(TokenType::None, format!("node {} right", index)))
            );
            let node = Node::new(
                Option::None,
                Option::Some(left),
                Option::Some(right),
                Option::Some(Token::new(TokenType::None, format!("node {}", index)))
            );
            vec.push(node.clone());

            if index == 0 {
                continue;
            }
            let prev = vec.get(index - 1);
            if prev.is_some() {
                prev.unwrap().borrow_mut().left_node = Some(node.clone());
                prev.unwrap().borrow_mut().right_node = Some(node.clone());
            }
        }

        let parent = Node::new(
            Option::None,
            Some(vec.first().unwrap().clone()),
            Option::None,
            Option::Some(Token::new(TokenType::None, "parent".to_string()))
        );

        parent.borrow().print_left();
    }
}


